package com.base.themvx

import android.animation.ObjectAnimator
import android.app.Activity
import android.graphics.Color
import android.os.Build
import android.os.SystemClock
import android.text.SpannableString
import android.text.Spanned
import android.util.TypedValue
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.annotation.StringRes
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.base.themvx.utils.ImageUtil
import com.base.themvx.utils.ScreenUtils

/**
 ******************(^_^)***********************<br>
 * Author: fee(QQ/WeiXin:1176610771)<br>
 * Date: 2023/7/28<br>
 * Time: 17:05<br>
 * <P>DESC:
 * 对　UI 的一些通用扩展
 * </p>
 * ******************(^_^)***********************
 */

var theViewClickGapTs = 1000L

/**
 * 让 View 是否使能 需要校验重复点击
 */
fun View?.enableCheckDoubleClick(isEnable: Boolean = true) {
    if (null == this) {
        return
    }
    val tagId = R.id.view_enable_click_tag_id
    setTag(tagId, isEnable)
}

/**
 * 扩展 [View]的快速点击场景下的 判断是否为有效的点击　以防重复点击
 */
fun View?.isValidClick(theGapTs: Long = theViewClickGapTs): Boolean {
    if (null == this) {
        return false
    }
    val enableTagId = R.id.view_enable_click_tag_id
    val enableTag = getTag(enableTagId)
    if (enableTag == false) {//当前 View 未开启需要校验重复点击
        return true
    }
    val tagId = R.id.view_double_click_tag_id
    val lastClickTime = getTag(tagId)
    val now = SystemClock.elapsedRealtime()
    if (lastClickTime == null) {
        setTag(tagId, now)
    } else {
        lastClickTime as Long
        //两次点击的时间间隔小于限制的间隔时间，则认为最后一次点击为无效点击
        if (now - lastClickTime < theGapTs) {
            return false
        }
        setTag(tagId, now)
    }
    return true
}

/**
 * 延迟初始化之：默认不进行　sync　的初始化
 */
fun <T> defNonSyncLazy(
    mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
    initializer: () -> T
) =
    lazy(mode = mode, initializer)

/**
 * 根据已知高及UI设计的宽、高比，计算出合适的宽
 * @param realHeight 已知的（目前真实的高）
 * @param theDesignWidth 设计图上的宽
 * @param theDesignHeight 设计图上的高
 */
fun calcSuitableWidthByDesignWh(realHeight: Int, theDesignWidth: Int, theDesignHeight: Int): Int {
    if (theDesignHeight > 0) {
        return theDesignWidth * realHeight / theDesignHeight
    }
    return 0
}

/**
 * 根据已知宽及UI设计的宽、高比，计算出合适的宽
 * @param realWidth 已知的（目前使用的）宽
 * @param theDesignWidth 设计图上的宽
 * @param theDesignHeight 设计图上的高
 */
fun calcSuitableHeightByDesignWh(realWidth: Int, theDesignWidth: Int, theDesignHeight: Int): Int {
    if (theDesignWidth > 0) {
        return theDesignHeight * realWidth / theDesignWidth
    }
    return 0
}


typealias CL = ConstraintLayout.LayoutParams


/**
 * 透明状态栏
 */
fun Activity?.transparentStatusBar(@ColorInt assignStatusBarColor: Int) {
    this?.window?.transparentStatusBar(assignStatusBarColor)
}

/**
 * 当前运行的Android系统的 SDK等级
 * eg.: 21 = Android 5.0
 */
val theApiLevel = Build.VERSION.SDK_INT

fun Window?.transparentStatusBar(@ColorInt assignStatusBarColor: Int = Color.TRANSPARENT) {
    if (this == null || theApiLevel < 19) return //Android 4.4以下不支持透明状态栏
    val translucentStatusFlag = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
    if (theApiLevel >= 21) { //Android 5.0+
        clearFlags(translucentStatusFlag)//把透明状态栏Flag移除，于下面的 Flag互斥
        addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
//        var options = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_FULLSCREEN
        if (assignStatusBarColor != 0 && theApiLevel >= 23) {//非透明
//            options = options or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            val vis = decorView.systemUiVisibility
            decorView.systemUiVisibility = vis or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        }
//        val vis = decorView.systemUiVisibility
//        decorView.systemUiVisibility = options or vis
        statusBarColor = assignStatusBarColor

    } else { //19 ~20
        addFlags(translucentStatusFlag)
    }
}


/**
 * 配置当前的　Activity 为沉浸式窗口
 * @param isNeedFullScreen 是否需要全屏显示，def = false
 * @param statusBarBgColor 指定的状态栏背景颜色，要使其生效，需要　[drawStatusBarBg] = true
 * @param drawStatusBarBg 是否需要在Android 5.0及以上 接管状态栏背景绘制，用于指定 状态栏背景颜色
 * @param isLightStatusBar 是否需要在Android 6.0(>=23)及以上 启用状态栏的灰色文字和图标 true: 开启亮色模式;　false: 开启暗黑模式
 * @param translucentNavBar 是否需要透明导航栏：如果[isNeedFullScreen] = true,则一般为true, 如果为true,则也会沉浸到状态栏,[drawStatusBarBg]为true也不会退出沉浸状态栏
 * @param hideNavigation 是否要隐藏导航栏： 如果[isNeedFullScreen] = true,一般为true,
 * @param navBarColor 底部导航栏颜色，如果App想在 [drawStatusBarBg] = true情况下(会退出沉浸式)，仍然要沉浸式到状态栏，但又不想透明/隐藏底部，则可以设定一个底部民航栏颜色来让系统再沉浸到状态栏目的
 */
fun Activity?.immersiveWindow(
    drawStatusBarBg: Boolean,
    isLightStatusBar: Boolean,
    translucentNavBar: Boolean,
    hideNavigation: Boolean,
    isNeedFullScreen: Boolean = false,
    @ColorInt statusBarBgColor: Int = 0,//如果该颜色值为 0：全透明状态：则一些设备上(三星/Vivo)需要去除： FLAG_TRANSLUCENT_STATUS flag，不然会有半透灰蒙层
    @ColorInt navBarColor: Int? = null
) {
    this?.window?.let { window ->
        window.attributes?.let { lp ->
            var mayExistVisibility = window.decorView.systemUiVisibility
            if (isNeedFullScreen) {
                window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            }
            val flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
            val flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
            if (theApiLevel >= 19) {//Android 4.4后才有沉浸式
                //默认实现透明　－　默认的实现沉浸式flag
                window.addFlags(flagTranslucentStatus) //(布局会延伸到顶部状态栏区域)
                if (translucentNavBar) { //透明底部虚拟导航栏(布局会延伸到底部虚拟导航栏区域)
                    window.addFlags(flagTranslucentNavigation)
                }
                if (theApiLevel >= 21) {//Android 5.0+ 才增加了设置状态栏颜色
                    if (drawStatusBarBg) {//如果需要 代替绘制状态栏的背景,则需要清除 FLAG_TRANSLUCENT_STATUS
                        window.clearFlags(flagTranslucentStatus)
                        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                    }
                    if (drawStatusBarBg) {
                        //Android 5.0+ 才增加了设置状态栏颜色(并且如果要自定义状态栏生效，还要上面两个属性即drawStatusBarBg=true)
                        window.statusBarColor = statusBarBgColor
                    }
//                    Android 5.0+ 才增加了设置状态栏颜色(并且如果要自定义状态栏生效，还要上面两个属性即drawStatusBarBg=true)
//                    window.statusBarColor = statusBarBgColor
                    if (navBarColor != null) {
                        if (!drawStatusBarBg) {
                            window.clearFlags(flagTranslucentStatus or flagTranslucentNavigation);
                            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                        } else {
                            window.clearFlags(flagTranslucentNavigation)
                        }
                        mayExistVisibility =
                            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
//                            View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
                                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        if (navBarColor == 0) {//透明时依照源码文档：增加以下两个属性
                            val fitTranslate =
                                View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            mayExistVisibility = mayExistVisibility or fitTranslate
                        }
                        window.navigationBarColor = navBarColor
                    }
                    if (theApiLevel >= 23) {//Android 6.0以上 实现状态栏字色和图标浅黑色主题
                        //当Activity　内容为亮色/白色/浅色背景时，需要让状态栏上的文字及图标变为深色(文字/icon为黑色)样式才看得清
                        val flagLightStatusBar =
                            View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR //理解为：在亮色主题下的状态栏
                        if (isLightStatusBar) {
                            mayExistVisibility = mayExistVisibility or flagLightStatusBar
                            //View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
//                            View.SYSTEM_UI_FLAG_FULLSCREEN
                        } else {//暗色模式：状态栏的字体、图标则为白色

                            val a = flagLightStatusBar.inv()
                            mayExistVisibility = mayExistVisibility and a
                            //等效与下面
//                            mayExistVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_VISIBLE //文字/icon 为白色
                        }
                    }
                } else {//19 ~5.0
                    //如果要改变状态栏背景颜色，则需要　自己使用　View来代替系统的，并且设置背景
                }
                if (hideNavigation) {//隐藏底部虚拟民航栏
                    val flag = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            or View.SYSTEM_UI_FLAG_IMMERSIVE
                            or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
                    mayExistVisibility = mayExistVisibility or flag
                }
//                lp.systemUiVisibility = mayExistVisibility //这个在设置　状态栏暗黑模式下，效果不太好(状态栏有背景)
                window.decorView.systemUiVisibility = mayExistVisibility
                window.attributes = lp
//                //view不根据系统窗口来调整自己的布局
//                val contentViewGroup: ViewGroup = window.findViewById(Window.ID_ANDROID_CONTENT)
//                val childView = contentViewGroup.getChildAt(0)
//                if (childView != null) {
//                    childView.fitsSystemWindows = false
//                    ViewCompat.requestApplyInsets(childView)
//                }
            }//theApiLevel >= 19 end
        }
    }
}


fun Activity?.assignStatusBarColor(@ColorInt color: Int) {
    if (null == this)
        return
    window?.let {
        window.statusBarColor = color
    }
}

/**
 * 单独的 修改(非隐藏/透明样式需求时)底部导航栏的颜色
 */
fun Activity?.assignNavigationBarColor(@ColorInt color: Int) {
    this?.window?.let { window ->
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
        window.navigationBarColor = color
    }
}

/**
 * 检出 Url的文件名
 */
fun String?.checkOutUrlFileName(byChar: Char = '/'): String {
    if (this == null) return ""
    val indexOfSeparator = indexOfLast { it == byChar }
    if (indexOfSeparator >= 0) {
        return substring(indexOfSeparator + 1)
    }
    return ""
}

/**
 * 让进度条动画的形式显示
 */
fun ProgressBar.animProgress(from: Int, to: Int, duration: Long = 1500) {
//    val animTag = tag
//    if (animTag is ObjectAnimator){
//        animTag.cancel()
//    }
    if (progress == to) {
        return
    }
    var realStart = from
    if (from < 0) {
        realStart = progress
    }
    ObjectAnimator.ofInt(this, "progress", realStart, to)
        .setDuration(duration)
        .start()
}

fun spanStyleText(
    srcText: CharSequence,
    keywordList: List<String>?,
    keywordList2: List<String>? = null,
    vararg styleableBlocks: (keywordIndex: Int) -> Any
): CharSequence {
    if (keywordList.isNullOrEmpty() || styleableBlocks.isEmpty()) {
        return srcText
    }
    val isHasKeywordList2 = !keywordList2.isNullOrEmpty()
    val spanableStr = SpannableString(srcText)
    var index = -1
    keywordList.forEach { keyword ->
        index++
        if (keyword.isNotBlank()) {
            val startIndex = srcText.indexOf(keyword)
            if (startIndex >= 0) {//匹配到了关键字
                val lenOfText = keyword.length
                val endIndex = startIndex + lenOfText
                styleableBlocks.forEach {
                    val styleSpan = it.invoke(index)
                    spanableStr.setSpan(
                        styleSpan,
                        startIndex,
                        endIndex,
                        Spanned.SPAN_INCLUSIVE_EXCLUSIVE
                    )
                }
            }
        }
        //匹配关键字2
        if (isHasKeywordList2) {
            val keyword2 = keywordList2?.get(index) ?: ""
            if (keyword2.isNotBlank()) {
                val startIndex = srcText.indexOf(keyword2)
                if (startIndex >= 0) {//匹配到了关键字
                    val lenOfText = keyword2.length
                    val endIndex = startIndex + lenOfText
                    styleableBlocks.forEach {
                        val styleSpan = it.invoke(index)
                        spanableStr.setSpan(
                            styleSpan,
                            startIndex,
                            endIndex,
                            Spanned.SPAN_INCLUSIVE_EXCLUSIVE
                        )
                    }
                }
            }
        }
//         startIndex = srcText.indexOf(keyword1)
//        if (startIndex < 0) {
//            return@forEach //continue
//        }
//        val lenOfText = keyword.length
//        val endIndex = startIndex + lenOfText
//        styleableBlocks.forEach {
//            val styleSpan = it.invoke(index)
//            spanableStr.setSpan(styleSpan, startIndex, endIndex, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
//        }
    }
    return spanableStr
}

fun Int.dpToPx(): Int {
    return ScreenUtils.dp2px(this.toFloat())
}

fun TextView.setTextSizePx(pxSize: Float) {
//    textSize = //这个是 sp 大小
    setTextSize(TypedValue.COMPLEX_UNIT_PX, pxSize)
}

/**
 * 请求显示/弹出 输入法
 */
fun View?.reqShowSoftInput() {
    if (null == this) {
        return
    }
    val curContext = context
    val inputManager: InputMethodManager? =
        curContext.getSystemService(InputMethodManager::class.java)
    if (inputManager != null) {
        requestFocus()
        inputManager.showSoftInput(this, 0)
    }
}

fun View?.reqHideSoftInput() {
    if (null == this) {
        return
    }
    val curContext = context
    val inputManager: InputMethodManager? =
        curContext.getSystemService(InputMethodManager::class.java)
    inputManager?.hideSoftInputFromWindow(windowToken, 0)
}

fun ImageView.loadImg(
    imgUrl: String,
    holdRes: Int = R.drawable.shape_4_def_img,
    errorRes: Int = R.drawable.shape_4_def_img,
    isUseAppContext: Boolean = false
) {
    if (imgUrl.isBlank()) {
        return
    }
    var theContext = this.context
    if (isUseAppContext) {
        theContext = theContext.applicationContext
    }
    ImageUtil.loadImage(theContext, imgUrl, holdRes, errorRes, this)
}

/**
 * 获取文本资源
 * 注：只适合当前语言状态下，如果切换了语言，需要重新获取
 */
fun getTextRes(@StringRes textResId: Int): String {
    return LibApplication.sApp.getString(textResId)
}


fun matchCurrencySymbol(currencyCode: String): String {
    return when (currencyCode) {
        "USD" -> "$"
        "VND" -> "₫"
        "KRW" -> "₩"
        "CNY" -> "¥"
        else -> ""
    }
}

/**
 * 根据当前View的状态判断才设置View的可见性
 *　目的为：不是每次都直接调用View的isVisible，因为如果已是可见，则可以不用调用让其可见，减少View的绘制(void setVisibility(@Visibility int visibility))
 * 有很多代码
 */
fun View?.visibleOrNot(isToVisibleOrNot: Boolean) {
    if(null == this) {
        return
    }
    if (isToVisibleOrNot) {
        if (!isVisible) {
            isVisible = true
        }
    } else {
        if (isVisible) {
            isVisible = false
        }
    }
}

fun View?.invisibleOrNot(isToInvisibleOrNot: Boolean) {
    if(null == this) {
        return
    }
    if (isToInvisibleOrNot) {
        if (!isInvisible) {
            isInvisible = true
        }
    } else {
        if (isInvisible) {
            isInvisible = false
        }
    }
}